﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SoulDoorEngine.Components.Smart2D.Basic;

namespace SoulDoorEngine.Components.Smart2D.Objects
{
    /// <summary>
    /// 物理引擎
    /// </summary>
    public class Physic
    {
        #region
        private GraphicObj _go;
        private float _Mass = 1f;
        private float _U = 0.9f;//2012.04.02修改
        private Vector _MaxVelocity = new Vector(20, 20);
        private Vector _G = new Vector(0f, AG);
        private float _Theta = 0f;
        private bool _OnGround = false;
        #endregion

        #region
        /// <summary>
        /// 接触地面
        /// </summary>
        public bool OnGround
        {
            get { return _OnGround; }
            set { _OnGround = value; }
        }
        /// <summary>
        /// 所在平面角度 为0~Pi
        /// </summary>
        public float Theta
        {
            get { return _Theta; }
            set { _Theta = value; }
        }
        /// <summary>
        /// GraphicObj 实例
        /// </summary>
        public GraphicObj Go
        {
            get { return _go; }
            set { _go = value; }
        }
        /// <summary>
        /// 质量
        /// </summary>
        public float Mass
        {
            get { return _Mass; }
            set { _Mass = value; }
        }
        /// <summary>
        /// 摩擦系数
        /// </summary>
        public float U
        {
            get
            {
                if (OnGround)
                {
                    return _U;
                }
                else
                {
                    return 0f;
                }
            }
            set { _U = value; }
        }
        /// <summary>
        /// 最大速度
        /// </summary>
        public Vector MaxVelocity
        {
            get { return _MaxVelocity; }
            set { _MaxVelocity = value; }
        }
        /// <summary>
        /// 重力加速度
        /// </summary>
        public Vector G
        {
            get { return _G; }
            set { _G = value; }
        }
        /// <summary>
        /// 速率
        /// </summary>
        public Vector Velocity
        {
            get { return this.Go.Velocity; }
            set { this.Go.Velocity = value; }
        }
        /// <summary>
        /// 加速度
        /// </summary>
        public Vector Acceleration
        {
            get { return this.Go.Acceleration; }
            set { this.Go.Acceleration = value; }
        }
        /// <summary>
        /// 重力加速度常数
        /// </summary>
        public const float AG = 1.0f;
        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        public Physic()
        { }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="go">GraphicObj 实例</param>
        public Physic(GraphicObj go)
        {
            this.Go = go;
        }

        /// <summary>
        /// 更新物理属性
        /// </summary>
        public void Update()
        {
            if (!OnGround)//自由落体
            {
                this.Acceleration = G;
            }
            else if (Math.Sin(Theta) > U * Math.Cos(Theta))//最大摩擦力小于下滑力的情况
            {
                this.Acceleration = new Vector((float)((AG * Math.Sin(Theta) - U * AG * Math.Cos(Theta)) * Math.Cos(Theta)),
                                    (float)((AG * Math.Sin(Theta) - U * AG * Math.Cos(Theta)) * Math.Sin(Theta)));
            }
            else if (Velocity.X == 0f)//水平方向速度为0则不考虑摩擦力
            {
                //落地情况
                if (Velocity.Y > 0)
                {
                    if (this.Velocity.Y - AG * 30 > 0)
                    {
                        this.Acceleration = new Vector(0, -AG * 50);
                    }
                    else
                    {
                        this.Velocity = new Vector(Velocity.X, 0);
                        this.Acceleration = Vector.Zero;
                    }
                }
                //else if (Velocity.Y <= 0)
                //{
                //    this.Velocity = Vector.Zero;
                //    this.Acceleration = Vector.Zero;
                //}
            }
            else if (Velocity.X != 0f)//水平方向速度不为0则考虑摩擦力
            {
                //落地情况
                if (Velocity.Y > 0)
                {
                    if (this.Velocity.Y - AG * 30 > 0)
                    {
                        this.Acceleration = new Vector(0, -AG * 50);
                    }
                    else
                    {
                        //////////////////////////////////////////////////////////////////////////
                        //////////////////////////////////////////////////////////////////////////
                        ////////////////////2012.04.02修改以支持物理引擎特效/////////////////////////
                        /////////////////////此部分增加物体着地后的弹性//////////////////////////////
                        //////////////////////////////////////////////////////////////////////////
                        if (this.Velocity.Y >= 0.4)
                        {
                            this.Velocity = new Vector(Velocity.X, -1f);
                            //this.Acceleration = new Vector(Velocity.X, 0f);
                        }
                        else
                        {
                            this.Velocity = new Vector(Velocity.X, 0);
                            this.Acceleration = Vector.Zero;
                        }
                    }
                }
                //////////////////////////////////////////////////////////////////////////
                //////////////////////////////////////////////////////////////////////////
                ////////////////////2012.04.02修改以支持物理引擎特效/////////////////////////
                //////////////////////////////////////////////////////////////////////////
                //////////////////////////////////////////////////////////////////////////
                //if (Velocity.Y == 0)
                //{
                //    this.Velocity = new Vector(Velocity.X, -1f);
                //    //this.Acceleration = new Vector(Velocity.X, 0f);
                //}
                //else//平移情况
                {
                    Vector temp = new Vector((float)((AG * Math.Sin(Theta) - U * AG * Math.Cos(Theta)) * Math.Cos(Theta)),
                                        (float)((AG * Math.Sin(Theta) - U * AG * Math.Cos(Theta)) * Math.Sin(Theta)));

                    //////////////////////////////////////////////////////////////////////////
                    //////////////////////////////////////////////////////////////////////////
                    /////////////////////2012.04.02修改///////////////////////////////////////
                    //////////////////////////////////////////////////////////////////////////
                    //////////////////////////////////////////////////////////////////////////
                    if (this.Velocity.X <= 0)
                    {
                        temp = -temp;//若物体向左移动，则考虑统一正方向，temp应取反
                    }
                    if (temp.X * this.Velocity.X <= 0)
                    {
                        //2012.04.02修改
                        this.Acceleration = temp;
                        //2012.04.02修改 防止左右抖动现象
                        if ((this.Acceleration.X + this.Velocity.X) * this.Velocity.X < 0)
                        {
                            this.Acceleration = new Vector(0, this.Acceleration.Y);
                            this.Velocity = new Vector(0, this.Velocity.Y);
                        }
                    }
                    else
                    {
                        this.Acceleration = new Vector(0, Acceleration.Y);
                        this.Velocity = new Vector(0, Velocity.Y);
                    }
                }
            }

            //////////////////////////////////////////////////////////////////////////
            //////////////////////////////////////////////////////////////////////////
            ////////////////////2012.04.02修改以支持物理引擎特效/////////////////////////
            /////////////////////////防止上下抖动与埋入地面以下///////////////////////////
            //////////////////////////////////////////////////////////////////////////
            if (this.OnGround && this.Velocity.Y >= 0.4f)
            {
                this.Acceleration += new Vector(0, -0.1f);
            }

            //将着地置为false否则将一直出于着地状态
            this.OnGround = false;
        }
    }
}
